// Copyright 2025 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/hash2/sha3.hpp>
#include <boost/core/lightweight_test.hpp>
#include <string>
#include <cstring>

std::string from_hex( char const* str )
{
    auto f = []( char c ) { return ( c >= 'a' ? c - 'a' + 10 : c - '0' ); };

    std::string s;
    while( *str != '\0' )
    {
        s.push_back( static_cast<char>( ( f( str[ 0 ] ) << 4 ) + f( str[ 1 ] ) ) );
        str += 2;
    }
    return s;
}

template<std::size_t D, class H> boost::hash2::digest<D> get_digest_result( H& h )
{
    boost::hash2::digest<D> r;

    std::size_t n = 0;

    for( ;; )
    {
        auto r2 = h.result();

        if( r2.size() >= r.size() - n )
        {
            std::memcpy( r.data() + n, r2.data(), r.size() - n );
            break;
        }

        std::memcpy( r.data() + n, r2.data(), r2.size() );
        n += r2.size();
    }

    return r;
}

template<class H, std::size_t D> std::string digest( std::string const& s )
{
    H h;

    h.update( s.data(), s.size() );

    return to_string( get_digest_result<D>( h ) );
}

static void shake_128()
{
    // https://en.wikipedia.org/wiki/SHA-3#Examples_of_SHA-3_variants
    // SHAKE128("", 256) => 32 byte digest, truncate from default of (1600 - 256) / 8 => 168
    using boost::hash2::shake_128;
    BOOST_TEST_EQ( (digest<shake_128, 32>( "" )), std::string( "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26" ) );

    // The block size of SHAKE-128 is 1344 bits / 168 bytes
    BOOST_TEST_EQ( shake_128::block_size, 168 );

    // selected samples from the download available here:
    // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Secure-Hashing
    std::pair<char const*, char const*> inputs[] =
    {
          /* expected hash */                 /* input message */

        // 8 bits / 1 byte
        { "fa996dafaa208d72287c23bc4ed4bfd5", "0e" },

        // 24 bits / 3 bytes
        { "d7335497e4cd3666885edbb0824d7a75", "1b3b6e" },

        // 48 bits / 6 bytes
        { "a07d5bd636c2ecca4b239124ef9fcac0", "cb1b0103501c" },

        // 72 bits / 9 bytes
        { "9dfe4efaa2c43081702cbfe8636859ce", "fc948f094aa4b4e035" },

        // 96 bits / 12 bytes
        { "56538d52b26f967bb9405e0f54fdf6e2", "84f6cb3dc77b9bf856caf54e" },

        // 1040 bits / 130 bytes
        { "32f96dbd1b30644a05413ae0ad892555", "93fdfb3cfda1ac94f20dc95c83dc129f9f14072ee5a85a43b741a565903d598b97f8f684744b829662533466857470177f9df8b63ecd60d617d6c2771961b42d9b32777e18ad718b3d99ddf33f25c2f4722821d318ad737e76af53712e2177d6c832e4f092ce62b9aa682eca59f7f07ca23eec4d1b517c85fc55be1976878acf4680" },

        // 1336 bits / 167 bytes
        { "b7b9db481898f888e5ee4ed629859844", "18636f702f216b1b9302e59d82192f4e002f82d526c3f04cbd4f9b9f0bcd2535ed7a67d326da66bdf7fc821ef0fff1a905d56c81e4472856863908d104301133ad111e39552cd542ef78d9b35f20419b893f4a93aee848e9f86ae3fd53d27fea7fb1fc69631fa0f3a5ff51267785086ab4f682d42baf394b3b6992e9a0bb58a38ce0692df9bbaf183e18523ee1352c5fad817e0c04a3e1c476be7f5e92f482a6fb29cd4bbf09ea" },

        // 1344 bits / 168 bytes
        { "f50af2684408915871948779a14c147c", "5d9ff9fe63c328ddbe0c865ac6ba605c52a14ee8e4870ba320ce849283532f2551959e74cf1a54c8b30ed75dd92e076637e4ad5213b3574e73d6640bd6245bc121378174dccdaa769e6e4f2dc650e1166c775d0a982021c0b160fe9438098e86b6cdc786f2a6d1ef68751551f7e99773daa28598d9961002c0b47ab511c8707df69f9b32796b723bf7685251d2c0d08567ad4e8540ddcc1b8a1a01f6c92aaaadcaf42301d9e53463" },

        // 1464 bits / 183 bytes
        { "4eaa27b085d08fc6a7473e672ea2ca1b", "aeacffca0e87bfdb2e6e74bfb67c9c90a8b6fb918b9be164cafcab7d570d8cd693bd8ee47243d3cbdaf921ce4d6e9e09c8b6d762eb0507bd597d976f6243e1f5e0d839e75ea72e2780da0d5e9f72a7a9b397548f762c3837c6a7c5d74b2081705ba70ab91adb5758e6b94058f2b141d830ff7b007538fb3ad8233f9e5bcbf6adcdd20843ee08d6c7d53cc3a58f53f3fe0997539e2f51d92e56990daad76dc816fd013b6d225634db140e9d2bbe7f45830406e44fee9d59" },

        // 1912 bits / 239 bytes
        { "4a39fc8528a74934ee03713a01359dd7", "12379c1ff308078314004e63994259135ad55ffce59d0a36c68ad65a060fbb91f1d60bf11cb29d0aa7d52bbbc043f94b6886b7b47aa3a942e94e055d495a9da39173bd3b1f0f5765fca25d5562116f417b6ab6b96cd2103792bf6df70b67790879787ba402097cbd9cd0add88796031e1ae924b0c311863c4a45d5ce551e96e8314b0bd4cf8756390dc8e0ed37b9fc0ace6bc844884754799748078a2e673e6a425635748e702b02d9f1c13b7b62a42c1e586b1bc25ec3170430c9d49f2ab7b633ffc32c45ae443f87b2176b5a7941ad9218d5dd793d193e1665e454af4f4af58cb07ba3fe28e919a075a924dde71c" },

        // 2168 bits / 271 bytes
        { "a52bf1c3e599d1dde7ee5062131e7875", "2eb70ab86a0e274462929641cd6feac9ec2f9061c022a97d7a04154733dad09cdd1d82577a1a51d38c99faabccbd20c41e2be48ec56eb586d39b6900e4308d230c42fa350ed8a919cf92c9150a8e0ed9448b4bbd034f434b3b47bdfd096ed647a36f9bd8900ed71e14c42a08efa95b0f4798ef77e28dfbd2985136c7085a52118bec8dca668583ea4478460be3d8b06f0d97f843caef8425d401fee54bbdaa88aa01f793fa05548645f644a64ee1b5ff7fd38eaa233f874cd59f3ddf385e86b5e9f601b9b256f2f901864d61988d11c98593d7335543ab4d85731a3e39078c9e3012d5c6f83f064b5e7089c529a46dd5081efe66c8c49932cac5be88b57e674d689f98423389388446fb1f5969ee70" },

        // 2384 bits / 298 bytes
        { "af0e9349fdd03458bb73328b44f300c1", "056563baad224be6c15792965dc2d392769546b9bdc8cef5c6b33a6e6adcc4fe6a0edee654ab2fbfab42d8b34264fbece9b47e4d4b3e0c60170a5d905ef0b8993dadb63cbb374837f44efb7478547b81ee5e5640fd8b03e06c95230b87a50661c56c7126a96f9f37e6a28543c6395b37ccbb57fa9958bc5b0c7c1348ada4b8404c71990ae5fa3ba8c767fe87f5bca1f8cdf208e4e74c3dba40e8b6ad9895d61d18e4b55238822470e0c4eca7cd8457ab372cf264b11090e6500192a30f1e66df72ee4e656aac637979e2d90d163a843853909be3bd4bbdc684ee3193dcea7270a2b7ebab4322ffa9dae94c209885318669478dcad4a6ca4123d81be3c59f01b7f066148c8b8c00ea4a00ce481b0e657fc178507fbec9c14177e6d6fd93e61c9ca423527009916f23134f" },

        // 2680 bits / 335 bytes
        { "177241c74dc8a061dd66cf2abaab284a", "37e780aa7d82aa7a6119556a002c8f9b0a73c51d6120ee54e36406a08334be3c9f4d72678e765bc2780506fa6aa404a6a955e47347b45e7ef57cd101184df0321fadb768134ca5806f8c257f33404d7834b4cab1b6ef1b013c34fe7c9fcf28535e0e39f5358def7af1b69a428289d0d95299611ed5578da5629375594140d0660578df561bc0a379a48c4d8b8006f691ab0b9004cd761d310ca21fe0252a4f34bbf391d2ef6d2845301526a2543f2767e8123fa9c5d4316fe468e25974140d85298837b2d61ce6a63e5a0ece28bccc25b1b65656e6f7332592eda70b55877220f63eba3ffa5645647661eb5821064b91ad00be535869891cbe39573ff10ae6cfcb1e00be83a2ad467f34a78869a40e7485f75de842b29d1c0f55d83d6f25d158502ef27a9989861602db28a6281e7b95e1a41c5dcc58d5ed2d48144df8609b842c7878ba6292389aa65c58fa85fdfc" },

        // 2688 bits / 336 bytes
        { "b4813895ae01b43c9d9ed85a8b03aaf4", "5d8f84b2f208b58a68e88ce8efb543a8404f0ec0c9805c760ad359d13faab84d3f8bb1d2a4bb45e72c0ec9245ffda2e572f94e466cffa44b876d5c5ed914d1ff338e06b74ad1e74d1405d23d759356661b7f3b03a7f7c2dc0d2c2dbe3d60822803408d472b752424ea76af1d79a0e7920388dde0c1903e9364b8d6d7b3b75430754b4d6b91cd83d5740866aab34bdbd0f1bd3dc504f1a1d753ba5f938241ce7f52544e0cc2018cc67b6401ce6abdbc8aafc5629bb643730fa3daced8f425787d61069910073ac760c631876fe81d1127034a544820ad3aa51cbf2d904f8cda936c063561a8a0bd0b1f1801777394630fb6f11cb68a588000861283a2dc9d7d2739ff2ae5ed5af5304cc176cd544a39a99064c1cb3b6bcc88a97ad9f6e381e8a3929781861e91f73516d3ee59d3661b5f584b4b717d0fa7a54da03674ac5fa36d3d76412a826c4c8445f7720337119198" },

        // 2696 bits / 337 bytes
        { "3109d9472ca436e805c6b3db2251a9bc", "a6fe00064257aa318b621c5eb311d32bb8004c2fa1a969d205d71762cc5d2e633907992629d1b69d9557ff6d5e8deb454ab00f6e497c89a4fea09e257a6fa2074bd818ceb5981b3e3faefd6e720f2d1edd9c5e4a5c51e5009abf636ed5bca53fe159c8287014a1bd904f5c8a7501625f79ac81eb618f478ce21cae6664acffb30572f059e1ad0fc2912264e8f1ca52af26c8bf78e09d75f3dd9fc734afa8770abe0bd78c90cc2ff448105fb16dd2c5b7edd8611a62e537db9331f5023e16d6ec150cc6e706d7c7fcbfff930c7281831fd5c4aff86ece57ed0db882f59a5fe403105d0592ca38a081fed84922873f538ee774f13b8cc09bd0521db4374aec69f4bae6dcb66455822c0b84c91a3474ffac2ad06f0a4423cd2c6a49d4f0d6242d6a1890937b5d9835a5f0ea5b1d01884d22a6c1718e1f60b3ab5e232947c76ef70b344171083c688093b5f1475377e3069863" },

        // 4048 bits / 506 bytes
        { "c609be05458f7ab33e7b6b54bc6e8999", "49d81708d86cd59dea0ac2c1017a9712d6dffb754dde0b57a9023a39fc5f5b6be276fc176f59f6826610428fac3a0e85fcf71011db061b8fcf2bf085ccd45670effb6dc46f4e3f2ed08e981c5935187fc95b86cf46da675096b1cf9591a67842d6301116be93d8288e4d6b70f1b1db8aa5d203b774a21825665b8170351ee86801da91154570eaf80a1564945af7822df8232fd04ea65593a7f2ab1e9e84cf6ad6c494c9ec2d9d27aaad2b8f7e4f33f12a17b422bc2d4724c13ff8a8b62054d1bfb5c33b9c11183cd8df67694300165ca37637b5a781155f1c070d156339a0242374c6723b6584bffb71c02b935455f8cb086392f5e8e8cc2015956d8f19daeb6aca4476b27108387a2ce0dc5591154d0b94ddc090abe8f4363036b821062baffb7fe550ea7dcd30bfd86c84710081e1c9e450475e123c5ec41f98ff0149bbf6405b5207cad1fb2f313d0f2bcee9be3f6ebe623049640d9234ab644a172ab14ba02633a339b5b9bb38226fda5694f7ec63ebbb8238eb8219ec9c429f4bf0353383a72f2d21702f5e3c513499f04852710f33044512edc47a56bad90885e5713851a7efac694b869fa590076e844ff757d95de581c1b3fa3dd8ccd28cad4f8ae173ee1b28f98ee606dca89063fbef0f262b33053f2c854debdc9cd433ab77abb64f445aa9b981761c4761767f3b71c2646c7b0d873baae50bc9f0" },

        // 5400 bits / 675 bytes
        { "aa01fa03bf2287b01f5a747c1536e103", "790c3f0fd4951582e17f64a586a5f43363b8fc9412798caead2c28fd9149b5e662749a4850af1f5598cf18a04d2cc876589d0072bea4874c21e5bef28add84da65d05896cd03bda90a2ce39958278345eaea0b792fbbfbc054a18f790a189e2d8908c220d5f8b926407f0bb830fced47228766d0ef28b0b14e46e1bb9b62cb88d705200feff6da7541b1d9275c15ce25075d59a186516ec818bdfde0c423d29355adba8aa465e73e15a8950b64d8ee87a2522b117aa0fdadb9ef2b0f0ec37cf50de9d7ba7aaea928c54e878fd1af1513f94f264a557b240739c3b370ffaa915707a2c0c7fb37e8dc588af7d82a010a74173d90749e4cac7ea120dc2c2140d9604abebed8af696b02d6432c11f73696500102b2b6de7a5ebbf8f0ef6bfcee1bb9de2717151dacfc4148636f60c1b68150c188d4399c6d0066461a3454161a2109cbc313a7cd696141b5d108ed0ee8931b5db53e25608d5a279486f310f92eb1f9197cfcb6470663ab25753fe16936935ae07337a1b34236a4e91c74c62d909431d138186914edca27a0375b6457074bb44fa908d51bf45a884dc4fe9f38aa9258fbe1b1e9bb845e5c2fffa69d62c481d2b43ffaea220b8f79c866dbc3a4e272169d5e0d5ec435e7f3d9b566b511d3fe5b161c530850ef9d1f63ea5159f9a2fe15c19774efb8672c93a741e4d4ec9d8af87e2a5b562c084c242538a98abd51fcfa6e7430c41d81f6e59f8b68207c8aec51f3505cfd3ebf642d17382b7d7a563570addd88067eed0d91cc7c3ac44803ee0d7d769c250e7aace53fd31e5bb71b711d85bac3dd6012393e33faa1e6d96e56d4248464f425a2edf1a7efcc4bfd0777a9fef32a704d584294deeee7afb534ed50f163fc950aa0effc57757b76d38211bd207005e8cc27ef3dd441524666be7b27ebf9ac2e45da7aac554e7403c1f40501f41a9c" },
    };

    for( auto const& input : inputs )
    {
        BOOST_TEST_EQ( (digest<shake_128, 16>( from_hex( input.second ) )), std::string( input.first ));
    }

    // SHAKE128VariableOut.rsp

    BOOST_TEST_EQ( (digest<shake_128, 352 / 8>( from_hex( "0b5173a10bdd6644ed165db4dec31784" ) )), std::string( "f96f5e18c12945f7d1bd8b38b4465e694ba06a36ca4d9e6c271863e95534867dbfa07517c095324b9cf3dc95" ));
    BOOST_TEST_EQ( (digest<shake_128, 896 / 8>( from_hex( "511af474bdb4c85547d47373c8fb4082" ) )), std::string( "50397c1f6d1244b8a3741c1d82dfbe6f9b4357cbd8f3c2046c2ee95a0ade85cc4650873b08271ac33c539ad4333e2a328da5ef2348e6716b34451450579eb06a514e70923c3c7d16b97681d1f88bbc342543d0574f2bf97340e0537b03a06c3f06ec0a8928a2bf1221f50104e1f46057" ));

    // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/ShortMsgKAT_SHAKE128.txt
    BOOST_TEST_EQ( (digest<shake_128, 512>( "" )), std::string( "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef263cb1eea988004b93103cfb0aeefd2a686e01fa4a58e8a3639ca8a1e3f9ae57e235b8cc873c23dc62b8d260169afa2f75ab916a58d974918835d25e6a435085b2badfd6dfaac359a5efbb7bcc4b59d538df9a04302e10c8bc1cbf1a0b3a5120ea17cda7cfad765f5623474d368ccca8af0007cd9f5e4c849f167a580b14aabdefaee7eef47cb0fca9767be1fda69419dfb927e9df07348b196691abaeb580b32def58538b8d23f87732ea63b02b4fa0f4873360e2841928cd60dd4cee8cc0d4c922a96188d032675c8ac850933c7aff1533b94c834adbb69c6115bad4692d8619f90b0cdf8a7b9c264029ac185b70b83f2801f2f4b3f70c593ea3aeeb613a7f1b1de33fd75081f592305f2e4526edc09631b10958f464d889f31ba010250fda7f1368ec2967fc84ef2ae9aff268e0b1700affc6820b523a3d917135f2dff2ee06bfe72b3124721d4a26c04e53a75e30e73a7a9c4a95d91c55d495e9f51dd0b5e9d83c6d5e8ce803aa62b8d654db53d09b8dcff273cdfeb573fad8bcd45578bec2e770d01efde86e721a3f7c6cce275dabe6e2143f1af18da7efddc4c7b70b5e345db93cc936bea323491ccb38a388f546a9ff00dd4e1300b9b2153d2041d205b443e41b45a653f2a5c4492c1add544512dda2529833462b71a41a45be97290b6f" ));
}

static void shake_256()
{
    // https://en.wikipedia.org/wiki/SHA-3#Examples_of_SHA-3_variants
    // SHAKE256("", 512) => 64 byte digest, truncate from default of (1600 - 512) / 8 => 136
    using boost::hash2::shake_256;
    BOOST_TEST_EQ( (digest<shake_256, 64>( "" )), std::string( "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be" ) );

    // The block size of SHAKE-256 is 1088 bits / 136 bytes
    BOOST_TEST_EQ( shake_256::block_size, 136 );

    // selected samples from the download available here:
    // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Secure-Hashing
    std::pair<char const*, char const*> inputs[] =
    {
          /* expected hash */                                                 /* input message */

        // 8 bits / 1 byte
        { "aabb07488ff9edd05d6a603b7791b60a16d45093608f1badc0c9cc9a9154f215", "0f" },

        // 16 bits / 2 bytes
        { "8e2df9d379bb034aee064e965f960ebb418a9bb535025fb96427f678cf207877", "0dc1" },

        // 64 bits / 8 bytes
        { "54f5dddb85f62dba7dc4727d502bdee959fb665bd482bd0ce31cbdd1a042e4b5", "587cb398fe82ffda" },

        // 240 bits / 30 bytes
        { "58273b2859043f1acc6d6a68f6d95417c5c5262ce653ee466999abe9069fa9f5", "7ad31b363f8929c7a262e01c75afdfa87020a8383c8752d7cae07feee98f" },

        // 376 bits / 47 bytes
        { "9620f7da5b7410fe8db4e77796f5570d5adef8a34417bc70e60ce68c571e8e1e", "43fa7c73c6196ef28d3ae734fd808c1d017eb964fd5418df041b73014a84c6a1dcbb99fc8e928cfe35db34bd171525" },

        // 632 bits / 79 bytes
        { "6aa9521d01f8d85a6f8d58f3a1cd5eee70a456bf12e39956787e929f667c93e1", "c00da5d029856847c0016b17065447476f6e3ae85b81c25547626bb84531e5d0a93c59f20621fd4e5933e774831f1f17fdd0f710c78f9fa5a16ff40c7ee8992b36c249a27b346b0b0e4ee780329439" },

        // 1080 bits / 135 bytes
        { "c6ce60c1852ea780ed845aac4ca6a30e09f5c0064c9675865178717cfeb1dc97", "362f1eb00b37a9613b1ae82b90452579d42f8b1f9ede95f86badc6cdf04c9b79af08be4bc94d7cac136979026b92a2d44d2b642ea1431b47d75fce61367919f171486a007cc271d19de0d1c4c6a11c7a2251fe3aee0bb8938a7dd043d0eb0758a4768c95cc9f6f1703075839487879b47c29c10b2c3e5326ac8f363c65aa4ef76f1b8bd363eb60" },

        // 1088 bits / 136 bytes
        { "e2e1c432dd07c2ee89a78f31211c92eeb5306c4fa4db93c4e5cd43080d6079e4", "d8f12b97f81d47aebbfb7314ff04172cf2be71c3778e238bcccdeecb691fbd542b00e5b7b1a0abb507f107f781fea700ea7e375fdea9e029754a0ea62216774bda3c59e8783d022360fe9625621c0d93e27f7bc03632942150716f019d048a752ccc0f93139c55df0f4aaa066a0550cf22e8c54e47d0475ba56b9842a392ffbc6bd98f1e4b64abd1" },

        // 1376 bits / 172 bytes
        { "17f4b2f60cb364da5e8a62db58e07eb1c44b888c433adc1e62461879cd271463", "fece673103322483b85340e991e478c2c15e2d795a98adb5b697b4cf17a733898aaa4ffd11b1add300c9edb7a818740a33286fd8cf82140b0f7f2bde8d5bce94d58b6d697e5015c99a8df1c051d611b2c8c96a4c48a11eba9c08fe1aba2d4d31a617c75d9439e2cb4d4654ead346d52048ea26bb0c1c522a26db346de54639cac6f668c299919f43e09c1f1f78914abd7b32ac0f641c39c3749fd5be55cd1ac6fed1557ed683d1981c395946" },

        // 1632 bits / 204 bytes
        { "d68ff8d635a0cb4df7166abf237260054493f5ba879129c56f08b2ba14234ef4", "1d9236eecb54cae3192273ee28afeb721a9c1a46be90db666f8a03e83976a0323eff7e6b58a5f02f000fcc876fa2b8180252a49ae3b8988ce665b026b1776590206a0d51e830a50a7a83cf642a7a1747905a7a4d2eaf2976549c8a1d4170802a8b79ec8ac11d74dc4e26836da05e90678a5ca445e79d168a81d799b331897a6a47d722fc2b95e20d45a2f08b1b77ace0b9ff286c56aae83234bde6d1c8ecd9b71b2ab79170c07905279c1ea4e1ecf21ae5ec10a8c3fc26d537f678604fbe2878d01bb42fd7c5c02dbcbf16a1" },

        // 1944 bits / 243 bytes
        { "a3a0137b93710d0f450357834dfbfa5992a8cd85d22d74bccd71e6dfd744b337", "8ad36cb261bca27cf75be4a016a06e3017d1833d542d749ce0d0fee975d6d8cdadc38d7d75238883bf6d6dc1782db0b3ba6260f442254304248c2848bdce7952eaa8106377ff4b2edbc663df2222f95c2accf2cb12b88554f0f49228c2d236c2a8499c6d50991606b12e6c03fcc774b4cfd7e2c9ac2b6215abcee4916b2a37a44e6fdaa1e6390f92aa6d3034ee634642124bd8f6f9c901cebce3c58ca01da58046e2710922265e5a2e4a597ae0409a8e59ef7b5bdfd98b078dfbde1f49f4a8dff76a0aadecaa2ce6a68e8cddbaa496210d8c74ff47a2274885ded7554ff86747c9cf4d932d0ba1bf7801736664d8628297ea6a" },

        // 2104 bits / 263 bytes
        { "97303e793263d13c231963b947d56828a6dc5aea6caddf57ccaa817e454c950f", "3a250047dffe58d4b6427ae94566d3d00026013925d5dd2fe5f1b94bc4fae62842847a16bb8c4f138c084ff777c1efee4965fa2bb9d890db94cc6e58179170a09c2e53057ab0c02626c2861d9e7e28fa07839771944840cfabb0493243de18fa914a167be314b2f4cc99a8c5814583dc83a860717ecbf6f371c4d3421088e81e670148e0bf602d67c5b53c56e9bc0a7d05fade943f09b92f303193ee4638e8f4667a739bd63c3a665b3dca389e8ec4c3d4a498429eac916b2e1e129fac951f65d8de1e16f04edfdad459dbd26861b9973acc17e46559868fb5b4d6be0b4895570354d2b8d54126a97933f68e0fdef2e27d9be1e05abaa1830b1a69b12bf852b3310516e94cbb17" },

        // 2168 bits / 271 bytes
        { "a7835b81740824ebfc4a0dda40da7a70a66f9f3a8ea77cf857664ff955c5c5fe", "a1ce406d09c02ca1c3cc97f25c9b96eeb9d3480c053b67edee201ce111f718adb243e08cb1b96873b9a2e499bb82db379bf77d8c29e3362552cd835b9885051dbf07d4f0c9a21533255acfa8248afa30acced9d6301f8a0fdf40dc401c5a60812fe3c3a13ac35a6a6ebaff267efc1c62541f05f104378b34fe40ce9987bc52626a9c55a8ea64609ffc8b1d1bb3206853fcb4a8e58b73601b1594016dc0f40347d8fd330cc3cd4f5a3794d090aa3e078d0a536bbbaf1b324d8e051ec4af499ab8e1cd05d5ac464e24879fc18b4b9e2098e8c5f67a56762850cf5bcda73c053f3dedd3720b8c168583547297177e88dcfafcd1f02a6acd6bae425eb51c4f6e1c5f64d823b74d861d0106d7fb392b4363" },

        // 2176 bits / 272 bytes
        { "46293a63c235750d58a24edca5ba637b96cae74325c6c8122c4155c0d15805e6", "104fefe89f08d15d36a2233f42a7defa917c5ad2642e06cac56d5cc51ad914ecfb7d984f4199b9cf5fa5a03bf69207b9a353a9681c9cf6437bea0c49d9c3e3db1f3fc76519c70c40cc1dfdd70a9c150943c272cf9eeb861f485f10100c8f4a3e259c6470501932782512225ba64d70b219cf9d5013a21d25d6d65062dcc6b3deb49d58b90d18933f118df70ff42c807ccc851233a34a221eca56b38971ef858475488988794a975d3894633a19c1ae2f05e9b9c0756affd3cfe823ccf29228f60fa7e025bc39a79943325126409460926b057a3fb28a1b098b938872883804fd2bc245d7fd6d29bcda6ca6198f2eff6ea7e03ef78133de8ba65fc8c45a688160719fa1e7646d878ea44c4b5c2e16f48b" },

        // 2184 bits / 273 bytes
        { "2bac5716803a9cda8f9e84365ab0a681327b5ba34fdedfb1c12e6e807f45284b", "dc5a100fa16df1583c79722a0d72833d3bf22c109b8889dbd35213c6bfce205813edae3242695cfd9f59b9a1c203c1b72ef1a5423147cb990b5316a85266675894e2644c3f9578cebe451a09e58c53788fe77a9e850943f8a275f830354b0593a762bac55e984db3e0661eca3cb83f67a6fb348e6177f7dee2df40c4322602f094953905681be3954fe44c4c902c8f6bba565a788b38f13411ba76ce0f9f6756a2a2687424c5435a51e62df7a8934b6e141f74c6ccf539e3782d22b5955d3baf1ab2cf7b5c3f74ec2f9447344e937957fd7f0bdfec56d5d25f61cde18c0986e244ecf780d6307e313117256948d4230ebb9ea62bb302cfe80d7dfebabc4a51d7687967ed5b416a139e974c005fff507a96" },

        // 3280 bits / 410 bytes
        { "21a48efd949c3f785179a0e340756a23f77d29a7625229a71a05731c7fbd5aa9", "16caf60da14b4fa9174a6d40c23cff93ed8fc9279990f749718db1500036ef2222498ffab86fa568a0611299e54e58d83281ac558d3f4d2541ee158b1c7d4d76dbffc64ae39925e3329f7fd894fa26fc1acdc22bc858a3438e1c55707a3f75ad2b33c48789937a24b34ddd85390611088cba3231b2a3a0a93e5d9a8780470fcff92cb03811234a330db353283b3bc3036f9125efb3eaed613bfa0c59975cc2e52c33b3e6e5123e1626190a4a0261e1f5ad9bc2ee34f331736b3bd26d274536f5ae90f5186c27fdd7e8c72972f64016e72d1d32b59b8715e5b867154b99cb140a668b9d560e2c307e3904d9297f9f07dfd7629ccc526e41c109c8fc7c53b604293c6cd42933e77e11031a42f605485fe893b129bcbf705c0f45a4b087bfcead5c187ac1174322909a2d4f8b61f001c4074951000c4c550ed5564458f444dab8aae2fe8daaa6a30d209fecddf2a893df46e18b4b4460e4011d23f01d4c49a4cc1c82405f6ac5339eac41385f3295c657ac43a72fed62e6daee94ef271638f292b8e18860de0699eb45fb7d3aa81f61d44158edd68ebc244451918b" },

        // 4376 bits / 547 bytes
        { "f7c566438926889d92f8d59c070bb2cdd7ea5c79cda501c7cf1fba605ce984fd", "fbcfacf7a3667d043ca2f2670d7fab8ede75cc610a43ac23d6ebd29901fe1d6f9c1942d71cb07c73ae0a7e75ca8dad050b3c8ce33e7e774db9219523ee9e08493f9f664d14be6d492b90f20b30e21b748e42ce1e84c269417bf8b4d8974914ff8c6801a0b319b94e5d3b367167055ea40e907b5b0595eac9c57917012586a95b2a7cf9192048c94ae91333ef967edf5d342c79e2e88262ab3faaa6e5bfde2f23c2e3380084d304057a20cfcde5d60566a820b2fb560e39b090954ace8ed80e20fba5a49d0643d146b66bf3527d94378911740cee77c3d8a06042e902b9fcae1a7ecb2737cf1f9ad745fb88c78640df8c172e71027228a54359b76cca69d277d9f25da81706efc67ed0d87474276364386358c88070c5096121febc6ec6e3d22400610e86d43cbd04ff0ba1a189842e559df9f9b098236dc1601fbf36f7b625c450e143ca618ce631799bf596d42ba5ab6d1aebda13c9372cbf205f6a25d3d98289e42e2bd46aabcce7905a9a2fe0310179c28846083fd16ae50b835177c357245373b7f3555b739ff0f3b7f7c22c3a216cf9b73ca00ea1437ce71334160d06725895c6680ee9a7703dcbf3f3b69628d1ecc7600303bd117f29bdf65b29394d363d5243d4249bad087520f8d733a763daa1356be458d487e59694160ed9d09636adb2167dc2f9ee2f41faadeb60e55304354ac127c7dc6d3e6b745a954e59483b4ebe28ac0e8cd2ac4962fa7666da60164d0f48147a5c2a524f66aa37af5cca0dc87d5f" },
    };

    for( auto const& input : inputs )
    {
        BOOST_TEST_EQ( (digest<shake_256, 32>( from_hex( input.second ) )), std::string( input.first ));
    }

    // SHAKE256VariableOut.rsp

    BOOST_TEST_EQ( (digest<shake_256, 352 / 8>( from_hex( "dc886df3f69c49513de3627e9481db5871e8ee88eb9f99611541930a8bc885e0" ) )), std::string( "00648afbc5e651649db1fd82936b00dbbc122fb4c877860d385c4950d56de7e096d613d7a3f27ed8f26334b0" ));
    BOOST_TEST_EQ( (digest<shake_256, 896 / 8>( from_hex( "e3ef127eadfafaf40408cebb28705df30b68d99dfa1893507ef3062d85461715" ) )), std::string( "7314002948c057006d4fc21e3e19c258fb5bdd57728fe93c9c6ef265b6d9f559ca73da32c427e135ba0db900d9003b19c9cf116f542a760418b1a435ac75ed5ab4ef151808c3849c3bce11c3cd285dd75e5c9fd0a0b32a89640a68e6e5b270f966f33911cfdffd03488b52b4c7fd1b22" ));

    // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/ShortMsgKAT_SHAKE256.txt
    BOOST_TEST_EQ( (digest<shake_256, 512>( "" )), std::string( "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be141e96616fb13957692cc7edd0b45ae3dc07223c8e92937bef84bc0eab862853349ec75546f58fb7c2775c38462c5010d846c185c15111e595522a6bcd16cf86f3d122109e3b1fdd943b6aec468a2d621a7c06c6a957c62b54dafc3be87567d677231395f6147293b68ceab7a9e0c58d864e8efde4e1b9a46cbe854713672f5caaae314ed9083dab4b099f8e300f01b8650f1f4b1d8fcf3f3cb53fb8e9eb2ea203bdc970f50ae55428a91f7f53ac266b28419c3778a15fd248d339ede785fb7f5a1aaa96d313eacc890936c173cdcd0fab882c45755feb3aed96d477ff96390bf9a66d1368b208e21f7c10d04a3dbd4e360633e5db4b602601c14cea737db3dcf722632cc77851cbdde2aaf0a33a07b373445df490cc8fc1e4160ff118378f11f0477de055a81a9eda57a4a2cfb0c83929d310912f729ec6cfa36c6ac6a75837143045d791cc85eff5b21932f23861bcf23a52b5da67eaf7baae0f5fb1369db78f3ac45f8c4ac5671d85735cdddb09d2b1e34a1fc066ff4a162cb263d6541274ae2fcc865f618abe27c124cd8b074ccd516301b91875824d09958f341ef274bdab0bae316339894304e35877b0c28a9b1fd166c796b9cc258a064a8f57e27f2a" ));
}

int main()
{
    shake_128();
    shake_256();

    return boost::report_errors();
}
